package com.cencat.common.utils;

import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.regex.Pattern;

/**
 * 短信工具类
 * 支持阿里云短信、腾讯云短信等主流服务商
 * 
 * @author cencat
 * @since 2024-01-01
 */
public class SmsUtils {
    
    private static final Logger log = LoggerFactory.getLogger(SmsUtils.class);

    private static SmsConfig smsConfig;
    private static final RestTemplate restTemplate = new RestTemplate();
    private static final Executor smsExecutor = Executors.newFixedThreadPool(3);
    
    // 手机号正则表达式
    private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");
    
    private SmsUtils() {
        // 私有构造函数，防止实例化
    }

    /**
     * 初始化短信配置
     * 
     * @param config 短信配置
     */
    public static void init(SmsConfig config) {
        smsConfig = config;
        log.info("短信工具初始化完成，服务商: {}", config.provider);
    }

    /**
     * 发送验证码短信
     * 
     * @param phone 手机号
     * @param code  验证码
     * @return 发送结果
     */
    public static SmsResult sendVerificationCode(String phone, String code) {
        return sendSms(phone, smsConfig.verificationTemplate, 
                      Map.of("code", code));
    }

    /**
     * 发送通知短信
     * 
     * @param phone   手机号
     * @param content 短信内容
     * @return 发送结果
     */
    public static SmsResult sendNotification(String phone, String content) {
        return sendSms(phone, smsConfig.notificationTemplate, 
                      Map.of("content", content));
    }

    /**
     * 发送模板短信
     * 
     * @param phone      手机号
     * @param templateId 模板ID
     * @param params     模板参数
     * @return 发送结果
     */
    public static SmsResult sendSms(String phone, String templateId, Map<String, Object> params) {
        try {
            // 参数校验
            validateParams(phone, templateId);
            
            SmsResult result;
            switch (smsConfig.provider) {
                case ALIYUN:
                    result = sendAliyunSms(phone, templateId, params);
                    break;
                case TENCENT:
                    result = sendTencentSms(phone, templateId, params);
                    break;
                case HUAWEI:
                    result = sendHuaweiSms(phone, templateId, params);
                    break;
                default:
                    result = SmsResult.failure("不支持的短信服务商: " + smsConfig.provider);
            }
            
            log.info("短信发送结果: phone={}, templateId={}, success={}, message={}", 
                    phone, templateId, result.success, result.message);
            
            return result;
            
        } catch (Exception e) {
            log.error("发送短信异常: phone={}, templateId={}, error={}", phone, templateId, e.getMessage(), e);
            return SmsResult.failure("发送短信异常: " + e.getMessage(), e);
        }
    }

    /**
     * 批量发送短信
     * 
     * @param phones     手机号列表
     * @param templateId 模板ID
     * @param params     模板参数
     * @return 发送结果列表
     */
    public static List<SmsResult> sendBatchSms(List<String> phones, String templateId, Map<String, Object> params) {
        return phones.stream()
                .map(phone -> sendSms(phone, templateId, params))
                .toList();
    }

    /**
     * 异步发送短信
     * 
     * @param phone      手机号
     * @param templateId 模板ID
     * @param params     模板参数
     * @return 异步结果
     */
    public static CompletableFuture<SmsResult> sendSmsAsync(String phone, String templateId, Map<String, Object> params) {
        return CompletableFuture.supplyAsync(() -> sendSms(phone, templateId, params), smsExecutor);
    }

    /**
     * 发送阿里云短信
     */
    private static SmsResult sendAliyunSms(String phone, String templateId, Map<String, Object> params) {
        try {
            // 构建请求参数
            Map<String, Object> requestParams = new HashMap<>();
            requestParams.put("PhoneNumbers", phone);
            requestParams.put("SignName", smsConfig.signName);
            requestParams.put("TemplateCode", templateId);
            requestParams.put("TemplateParam", JsonUtils.toJson(params));
            
            // 添加公共参数
            requestParams.put("AccessKeyId", smsConfig.accessKeyId);
            requestParams.put("Action", "SendSms");
            requestParams.put("Version", "2017-05-25");
            requestParams.put("RegionId", "cn-hangzhou");
            requestParams.put("Timestamp", DateUtils.formatDateTime(LocalDateTime.now()));
            requestParams.put("SignatureMethod", "HMAC-SHA1");
            requestParams.put("SignatureVersion", "1.0");
            requestParams.put("SignatureNonce", CencatStringUtils.generateRandomString(16));
            
            // 生成签名
            String signature = generateAliyunSignature(requestParams, smsConfig.accessKeySecret);
            requestParams.put("Signature", signature);
            
            // 发送请求
            HttpHeaders headers = new HttpHeaders();
            headers.set("Content-Type", "application/x-www-form-urlencoded");
            
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestParams, headers);
            ResponseEntity<String> response = restTemplate.exchange(
                    smsConfig.endpoint, HttpMethod.POST, entity, String.class);
            
            // 解析响应
            @SuppressWarnings("unchecked")
            Map<String, Object> responseMap = JsonUtils.parseObject(response.getBody(), Map.class);
            String code = (String) responseMap.get("Code");
            String message = (String) responseMap.get("Message");
            
            if ("OK".equals(code)) {
                return SmsResult.success("短信发送成功", (String) responseMap.get("BizId"));
            } else {
                return SmsResult.failure("短信发送失败: " + message);
            }
            
        } catch (Exception e) {
            log.error("阿里云短信发送异常: {}", e.getMessage(), e);
            return SmsResult.failure("阿里云短信发送异常: " + e.getMessage(), e);
        }
    }

    /**
     * 发送腾讯云短信
     */
    private static SmsResult sendTencentSms(String phone, String templateId, Map<String, Object> params) {
        try {
            // 构建请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("PhoneNumberSet", new String[]{phone});
            requestBody.put("SmsSdkAppId", smsConfig.appId);
            requestBody.put("SignName", smsConfig.signName);
            requestBody.put("TemplateId", templateId);
            requestBody.put("TemplateParamSet", params.values().toArray());
            
            // 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set("Content-Type", "application/json");
            headers.set("Authorization", generateTencentAuth());
            headers.set("X-TC-Action", "SendSms");
            headers.set("X-TC-Version", "2021-01-11");
            headers.set("X-TC-Region", "ap-guangzhou");
            
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
            ResponseEntity<String> response = restTemplate.exchange(
                    smsConfig.endpoint, HttpMethod.POST, entity, String.class);
            
            // 解析响应
            @SuppressWarnings("unchecked")
            Map<String, Object> responseMap = JsonUtils.parseObject(response.getBody(), Map.class);
            @SuppressWarnings("unchecked")
            Map<String, Object> responseData = (Map<String, Object>) responseMap.get("Response");
            
            if (responseData.containsKey("Error")) {
                @SuppressWarnings("unchecked")
                Map<String, Object> error = (Map<String, Object>) responseData.get("Error");
                return SmsResult.failure("腾讯云短信发送失败: " + error.get("Message"));
            } else {
                @SuppressWarnings("unchecked")
                List<Map<String, Object>> sendStatusSet = (List<Map<String, Object>>) responseData.get("SendStatusSet");
                if (!sendStatusSet.isEmpty()) {
                    Map<String, Object> status = sendStatusSet.get(0);
                    String code = (String) status.get("Code");
                    if ("Ok".equals(code)) {
                        return SmsResult.success("短信发送成功", (String) status.get("SerialNo"));
                    } else {
                        return SmsResult.failure("短信发送失败: " + status.get("Message"));
                    }
                }
            }
            
            return SmsResult.failure("短信发送失败: 未知错误");
            
        } catch (Exception e) {
            log.error("腾讯云短信发送异常: {}", e.getMessage(), e);
            return SmsResult.failure("腾讯云短信发送异常: " + e.getMessage(), e);
        }
    }

    /**
     * 发送华为云短信
     */
    private static SmsResult sendHuaweiSms(String phone, String templateId, Map<String, Object> params) {
        try {
            // 构建请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("from", smsConfig.signName);
            requestBody.put("to", phone);
            requestBody.put("templateId", templateId);
            requestBody.put("templateParas", JsonUtils.toJson(params));
            
            // 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set("Content-Type", "application/json");
            headers.set("Authorization", "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"");
            headers.set("X-WSSE", generateHuaweiWsse());
            
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
            ResponseEntity<String> response = restTemplate.exchange(
                    smsConfig.endpoint, HttpMethod.POST, entity, String.class);
            
            // 解析响应
            @SuppressWarnings("unchecked")
            Map<String, Object> responseMap = JsonUtils.parseObject(response.getBody(), Map.class);
            String code = (String) responseMap.get("code");
            String description = (String) responseMap.get("description");
            
            if ("000000".equals(code)) {
                return SmsResult.success("短信发送成功", (String) responseMap.get("result"));
            } else {
                return SmsResult.failure("华为云短信发送失败: " + description);
            }
            
        } catch (Exception e) {
            log.error("华为云短信发送异常: {}", e.getMessage(), e);
            return SmsResult.failure("华为云短信发送异常: " + e.getMessage(), e);
        }
    }

    /**
     * 生成阿里云签名
     */
    private static String generateAliyunSignature(Map<String, Object> params, String accessKeySecret) {
        // 实现阿里云签名算法
        // 这里简化处理，实际项目中需要完整实现
        return SecurityUtils.hmacSha1(JsonUtils.toJson(params), accessKeySecret + "&");
    }

    /**
     * 生成腾讯云认证信息
     */
    private static String generateTencentAuth() {
        // 实现腾讯云认证算法
        // 这里简化处理，实际项目中需要完整实现
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        String signature = SecurityUtils.hmacSha256(timestamp, smsConfig.getAccessKeySecret());
        return String.format("TC3-HMAC-SHA256 Credential=%s/%s, SignedHeaders=content-type;host, Signature=%s",
                smsConfig.getAccessKeyId(), timestamp, signature);
    }

    /**
     * 生成华为云WSSE认证
     */
    private static String generateHuaweiWsse() {
        // 实现华为云WSSE认证算法
        // 这里简化处理，实际项目中需要完整实现
        String nonce = CencatStringUtils.generateRandomString(16);
        String created = DateUtils.formatDateTime(LocalDateTime.now());
        String passwordDigest = SecurityUtils.sha256(nonce + created + smsConfig.getAccessKeySecret());
        
        return String.format("UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"",
                smsConfig.getAccessKeyId(), passwordDigest, nonce, created);
    }

    /**
     * 参数校验
     */
    private static void validateParams(String phone, String templateId) {
        if (smsConfig == null) {
            throw new IllegalStateException("短信配置未初始化，请先调用init方法");
        }
        
        if (CencatStringUtils.isBlank(phone)) {
            throw new IllegalArgumentException("手机号不能为空");
        }
        
        if (!PHONE_PATTERN.matcher(phone).matches()) {
            throw new IllegalArgumentException("手机号格式不正确: " + phone);
        }
        
        if (CencatStringUtils.isBlank(templateId)) {
            throw new IllegalArgumentException("模板ID不能为空");
        }
    }

    /**
     * 短信配置类
     */
    public static class SmsConfig {
        private SmsProvider provider;          // 服务商
        private String endpoint;               // 接口地址
        private String accessKeyId;            // 访问密钥ID
        private String accessKeySecret;        // 访问密钥Secret
        private String appId;                  // 应用ID（腾讯云）
        private String signName;               // 签名名称
        private String verificationTemplate;   // 验证码模板
        private String notificationTemplate;   // 通知模板
        private int timeout = 30000;          // 超时时间（毫秒）
        private int retryCount = 3;           // 重试次数
        
        public SmsConfig(SmsProvider provider, String endpoint, String accessKeyId, String accessKeySecret, String signName) {
            this.provider = provider;
            this.endpoint = endpoint;
            this.accessKeyId = accessKeyId;
            this.accessKeySecret = accessKeySecret;
            this.signName = signName;
        }
        
        // Getter and Setter methods
        public SmsProvider getProvider() {
            return provider;
        }
        
        public void setProvider(SmsProvider provider) {
            this.provider = provider;
        }
        
        public String getEndpoint() {
            return endpoint;
        }
        
        public void setEndpoint(String endpoint) {
            this.endpoint = endpoint;
        }
        
        public String getAccessKeyId() {
            return accessKeyId;
        }
        
        public void setAccessKeyId(String accessKeyId) {
            this.accessKeyId = accessKeyId;
        }
        
        public String getAccessKeySecret() {
            return accessKeySecret;
        }
        
        public void setAccessKeySecret(String accessKeySecret) {
            this.accessKeySecret = accessKeySecret;
        }
        
        public String getAppId() {
            return appId;
        }
        
        public void setAppId(String appId) {
            this.appId = appId;
        }
        
        public String getSignName() {
            return signName;
        }
        
        public void setSignName(String signName) {
            this.signName = signName;
        }
        
        public String getVerificationTemplate() {
            return verificationTemplate;
        }
        
        public void setVerificationTemplate(String verificationTemplate) {
            this.verificationTemplate = verificationTemplate;
        }
        
        public String getNotificationTemplate() {
            return notificationTemplate;
        }
        
        public void setNotificationTemplate(String notificationTemplate) {
            this.notificationTemplate = notificationTemplate;
        }
        
        public int getTimeout() {
            return timeout;
        }
        
        public void setTimeout(int timeout) {
            this.timeout = timeout;
        }
        
        public int getRetryCount() {
            return retryCount;
        }
        
        public void setRetryCount(int retryCount) {
            this.retryCount = retryCount;
        }
    }

    /**
     * 短信服务商枚举
     */
    public enum SmsProvider {
        ALIYUN("阿里云"),
        TENCENT("腾讯云"),
        HUAWEI("华为云");
        
        private final String name;
        
        SmsProvider(String name) {
            this.name = name;
        }
        
        public String getName() {
            return name;
        }
    }

    /**
     * 短信发送结果
     */
    public static class SmsResult {
        private boolean success;              // 是否成功
        private String message;               // 结果消息
        private String messageId;             // 消息ID
        private LocalDateTime sendTime;       // 发送时间
        private Exception exception;          // 异常信息
        
        public SmsResult() {
            this.sendTime = LocalDateTime.now();
        }
        
        public SmsResult(boolean success, String message) {
            this();
            this.success = success;
            this.message = message;
        }
        
        public static SmsResult success(String message) {
            return new SmsResult(true, message);
        }
        
        public static SmsResult success(String message, String messageId) {
            SmsResult result = new SmsResult(true, message);
            result.setMessageId(messageId);
            return result;
        }
        
        public static SmsResult failure(String message) {
            return new SmsResult(false, message);
        }
        
        public static SmsResult failure(String message, Exception exception) {
            SmsResult result = new SmsResult(false, message);
            result.setException(exception);
            return result;
        }
        
        // Getter and Setter methods
        public boolean isSuccess() {
            return success;
        }
        
        public void setSuccess(boolean success) {
            this.success = success;
        }
        
        public String getMessage() {
            return message;
        }
        
        public void setMessage(String message) {
            this.message = message;
        }
        
        public String getMessageId() {
            return messageId;
        }
        
        public void setMessageId(String messageId) {
            this.messageId = messageId;
        }
        
        public LocalDateTime getSendTime() {
            return sendTime;
        }
        
        public void setSendTime(LocalDateTime sendTime) {
            this.sendTime = sendTime;
        }
        
        public Exception getException() {
            return exception;
        }
        
        public void setException(Exception exception) {
            this.exception = exception;
        }
    }

    /**
     * 短信常量
     */
    public static class SmsConstants {
        // 模板类型
        public static final String TEMPLATE_VERIFICATION = "verification";  // 验证码
        public static final String TEMPLATE_NOTIFICATION = "notification";  // 通知
        public static final String TEMPLATE_MARKETING = "marketing";        // 营销
        
        // 验证码长度
        public static final int CODE_LENGTH_4 = 4;
        public static final int CODE_LENGTH_6 = 6;
        public static final int CODE_LENGTH_8 = 8;
        
        // 发送限制
        public static final int MAX_PHONE_LENGTH = 11;                     // 最大手机号长度
        public static final int MAX_CONTENT_LENGTH = 500;                  // 最大内容长度
        public static final int MAX_BATCH_SIZE = 100;                      // 最大批量发送数量
        
        // 时间限制
        public static final int SEND_INTERVAL_SECONDS = 60;               // 发送间隔（秒）
        public static final int DAILY_LIMIT = 10;                         // 每日限制次数
        
        private SmsConstants() {
            // 私有构造函数
        }
    }
}